メインコンテンツに移動

メインナビゲーション

  • ホーム
  • サイトマップ
  • ビデオ
  • ご連絡

パンくず

  • ホーム
  • DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成

DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成

drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

Entityの管理フォーム:一覧表示/追加/削除/更新 操作ができるようにする

  • 前回紹介した(DrupalのEntityを定義する簡単な例 )では、データを直接にDBに書き込むか、Feedsでcsvフォーマットデータをインポートする方法となります
    • 前回の例に一つEntityプロパティを追加します(sys_name)
    • これはコンテンツタイプなどを追加するときによく見られる名前とシステム名のペアです
    • 今回の例では:名前は「room_number」、システム名は「sys_name」にします
    • DBにもこのフィールドを追加します(カスタムモジュールのinstallファイルにあるスキーマに記入しました)
  • モジュール(Entity API)がEnitityに関する管理フォームが提供しています
    • 今回のカスタムモジュール(entity_example_2.zip)をダウンロードして、テストサイトにインストールし、動作を確認できます
    • 作成されたEntity一覧の表示
      EntityAPIに提供されたエンティティ一覧表示
    • Entityの新規作成/編集/追加操作もあります
      EntityAPIに提供された追加/更新/削除操作

Entityの管理フォームを表示させるため「EntityAPIControllerExportable」を使用します

  • Entityを定義(hook_entity_info() )する部分に「controller class」を「EntityAPIControllerExportable」を使用します
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'RoomController',     // EntityAPIControllerExportableの使用
    //        'controller class' => 'EntityAPIController',// <-前回使用したもの: デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            ・・・・・・・
        );
    
    // Entityの「controller class」のコールバッククラス
    class RoomController extends EntityAPIControllerExportable {
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        /**
         * Create a room - we first set up the values that are specific
         * to our room schema but then also go through the EntityAPIController
         * function.
         */
        public function create(array $values = array()) {
            // Add values that are specific to our Room
            $values += array(
                'rid' => '',
                'is_new' => TRUE,
                'type' => '',
                'room_number' => '',
                'sys_name' => '',
            );
            $room = parent::create($values);
            return $room;
        }
    }
  • Entity管理フォームをコンテンツ管理ページ(例)に挿入するために「admin ui」パラメターを定義します
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
        $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
       ・・・・・
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
            'admin ui' => array(
                'path' => 'admin/structure/rooms',
                'file' => 'rooms.admin.inc',
                'controller class' => 'RoomsUIController',
            ),
    
        );
    
        return $services;
    }
  • 管理UI定義は「rooms.admin.inc」ファイルに書きこみます(room.module内で記述することもできます)
    /**
     * UI controller.
     */
    class RoomsUIController extends EntityDefaultUIController {
    
      /**
       * Overrides hook_menu() defaults.
       */
      public function hook_menu() {
        $items = parent::hook_menu();
    	$items[$this->path]['description'] = t('Manage rooms. including adding
    		and removing fields and the display of fields.');
        return $items;
      }
    }
    
    /**
     * Generates the room editing form.
     */
    function room_form($form, &$form_state, $room, $op = 'edit') {
    
      if ($op == 'clone') {
        $room->sys_name .= ' (cloned)';
        $room->room_number = '';
      }
    
      $form['room_number'] = array(
        '#title' => t('Room Number'),
        '#type' => 'textfield',
        '#default_value' => isset($room->room_number)?$room->room_number : "",
        '#description' => t('Entry the Room number.'),
        '#required' => TRUE,
        '#size' => 30,
      );
    
      // Machine-readable type name.
      $form['sys_name'] = array(
        '#type' => 'machine_name',
        '#default_value' => isset($room->sys_name) ? $room->sys_name : '',
        '#maxlength' => 32,
        '#machine_name' => array(
          'exists' => 'room_get_sys_names',
          'source' => array('label'),
        ),
        '#description' => t('A unique machine-readable name for this model type. It must only contain lowercase letters, numbers, and underscores.'),
      );
    
      $form['type'] = array(
          '#title' => t('Room Type'),
          '#type' => 'textfield',
          '#default_value' => isset($room->type) ? $room->type : "",
          '#description' => t('Entry the Room type.'),
          '#required' => TRUE,
          '#size' => 60,
      );
    
    
      $form['actions'] = array('#type' => 'actions');
      $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save Room'),
        '#weight' => 40,
      );
    
      return $form;
    }
    
    /**
     * Form API submit callback for the type form.
     */
    function room_form_submit(&$form, &$form_state) {
      $room = entity_ui_form_submit_build_entity($form, $form_state);
      $room->save();
      $form_state['redirect'] = 'admin/structure/rooms';
    }
    
    
  • 以上の定義で、Entityの管理操作ができるようになります

 

添付 サイズ
entity_example_2.zip (3.28 KB) 3.28 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
drupal
video
entity type

Entityを定義する簡単な例:Roomエンティティ(Entityのサンプロモジュール:entity_example)

  • Entityをプログラミングで定義するには、最初簡単なこと、必要最小限のことを定義します
  • ここで、ルーム(Room)エンティティ(Entity)を例として紹介します(サンプルモジュールをダウンロードしてください)
    Roomエンティティ例とします

Roomエンティティ:Entityの定義 + データインポート + Entityの参照

  • Roomのテストデータ(dsvフォーマット): 

    • ルームナンバー: room_number

    • ルームタイプ:: type
      rid,room_number,type
      1,1001,シングル
      2,1002,シングル
      3,1003,シングル
      4,2001,ダブル
      5,3001,ダブル
  • データベース上に「room」テーブルを作成、または、モジュールのinstallファイルでスキーマを定義して、モジュールがインストール時に自動的に作成されます
    /**
     * Implement hook_schema()
     */
    function entity_example_schema(){
        $schema['room']=array(
            'description' => 'Rooms',
            'fields' => array(
                'rid' => array(
                    'type' => 'serial',
                    'description' => 'Room Id'
                ),
                'type' => array(
                    'type' => 'varchar',
                    'length' => '255',
                    'description' => 'Room Type'
                ),
                'room_number' => array(
                    'type' => 'varchar',
                    'length' => '25',
                    'description' => 'Room Number'
                ),
    
            ),
            'primary key' => array('rid'),
    
        );
    
        return $schema;
    }
  • モジュールファイル(.module)にRoomエンティティを定義します
    /**
     * Implements hook_entity_info().
     */
    /**
     * Implements hook_entity_info().
     */
    function entity_example_entity_info()
    {
    
       $services['room'] = array(
            'label' => t('Room'),                       // エンティティ名
            'entity class' => 'Entity',                 // デフォルトクラスの使用
            'controller class' => 'EntityAPIController',// デフォルトクラスの使用
            'base table' => 'room',                     // DB上のテーブル名
            'fieldable' => TRUE,                        // 余分のフィールド追加可能
            'entity keys' => array(                     // ルームIDをエンティティのキー.
                'id' => 'rid',
                'label' => 'room_number',               // コールバック関数が優先
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Default'),
                    'custom settings' => FALSE,
                ),
            ),
            'bundles' => array(),                       // bundleはこのエンティティ自身
    //        'label callback' => 'room_label',       // 指定しないとラベルの取得ができない
            'access callback' => 'room_access' ,        // default:'value user_access'動作しない
            'module' => 'entity_example',
            'metadata controller class' => 'EntityExampleMetadataController',
    
        );
    
        return $services;
    }
    
    /**
     * Extend the defaults.
     */
    class EntityExampleMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo() {
            $info = parent::entityPropertyInfo();
            $properties = &$info[$this->type]['properties'];
            $properties['type'] = array(
                'label' => t('Room type'),
                'schema field' => 'type',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('Room type of the room'),
            );
            $properties['room_number'] = array(
                'label' => t('Room Number'),
                'schema field' => 'room_number',
                'getter callback' => 'entity_property_getter_method',
                'setter callback' => 'entity_property_verbatim_set',
                'required' => TRUE,
                'description' => t('The number of the room'),
            )
            return $info;
        }
    }
    
    function room_access($op, $room = NULL, $account = NULL) {
        // 全員アクセス可能にする
        return TRUE;
    }
    
    
  • これだけで、Entityの定義が完了しました
  • モジュール(Feeds)でRoomサンプルデータをDBにインポートします
    • モジュール(Feeds Entity Processor)のインストール/有効化が必要
  • 実際にRoomエンティティが動作しているかをテストします
    • 任意のコンテンツタイプ(例:記事)Roomフィールドを追加します(Entity参照タイプ)
    • Entity参照タイプのターゲットを「Room」にします
    • 一つの記事を作成して、Roomエンティティの動作を確認します

Enity定義の注意点:アクセス権限、エンティティのラベル定義を正しく定義します

  • 上記例として、Entityの必要な最低限な定義となります
  • ネットでEntity定義例がありますが、アクセス権限、エンティティのラベルなどの権限が間違いやすいです
  • アクセス権限(access callback)で定義しないと、エンティティのラベルがうまく表示されないです
    Entityのアクセスコールバックが定義しないとラベルがうまく表示されない
  • エンティティのラベルを2か所で定義できます
    • entity_keys: DB上にどのフィールドがラベルとして利用するかを指定します
    • label callback : ユーザー必要応じて、ラベルを生成するコールバック関数
    • コールバック関数がentity_keys設定より優先です
      Entityのラベル設定

 

 

 

添付 サイズ
entity_example.zip (1.87 KB) 1.87 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

カスタムモジュールでEntityの定義と作成

  • シリーズ記事でEntityの定義、管理を説明しました
    • DrupalのEntityを定義する簡単な例
    • DrupalのEntityを定義する簡単な例-2:エンティティ管理フォーム
  • 定義されたEntityが拡張フィールドの使用はできません
    • そのEntityのバンドル(Bundle)の定義がしなかったからです

カスタムモジュール(entity_room.zip)でEntityとそのBundleを定義し、拡張フィールドの使用ができるようにします

  • 拡張フィールドがEntityオブジェクトが作成後に必要に応じ追加することができます(柔軟性を高める)
    • カスタムモジュール(entity_room.zip)をダウンロードして、参考にしてください
  • 定義されたRoom EntityにRoomバンドル(Bundle)を指定します
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $room_info['room'] = array(
            'label' => t('Room'),
            'controller class' => 'RoomController',
            'base table' => 'room',
            'uri callback' => 'room_uri',
            'fieldable' => TRUE,
            'entity keys' => array(
                'id' => 'rid',
                'label' => 'room_number',
            ),
            'static cache' => TRUE,
            'bundles' => array(       // バンドルの指定
                'room'=> array(         //  バンドル名: room
                    'label' => 'Room',
                    'admin' => array(
                        'path' => 'admin/structure/room/manage',  // バンドルの管理URI
                        'access arguments' => array('administer rooms'),
                    ),
                ),
            ),
            'view modes' => array(
                'full' => array(
                    'label' => t('Full Room'),
                    'custom settings' =>  FALSE,
                ),
            )
        );
    
        return $room_info;
    }
  • 管理画面(/admin/stracture/room/manage)でRoomEntityの拡張フィールドの追加ができるようになります
    • 例: Room Typeの追加
      バンドルに拡張フィールドの追加

Entity作成時に追加された拡張フィールドが現れます

  • Roomエンティティを作成(/room/add)画面に、Roomエンティティのプロパティ(room_number)と拡張フィールド(room type)が現れます
    Entity作成フォームに追加したフィールド(Room Type)が現れ
  • エンティティ表示画面(/room/[rid])にも拡張フィールドの内容が表示されます
    Entity表示画面に追加されたフィールドの内容が表示される
  • エンティティ追加、表示のコードは以下のよう
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // 管理が面にメッセージ表示のみ
        $items['admin/structure/room/manage'] = array(
            'title' => 'Room Admin',
            'description' => 'Manage Room structure',
            'page callback' => 'room_info',
            'access arguments' => array('administer rooms'),
        );
        // 個別Room表示
        $items['room/%entity_room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
        // 新規Room作成
        $items['room/add'] = array(
            'title' => t('Add Room'),
            'page callback' => 'room_add',
            'access arguments' => array('create room'),
        );
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * create "add room" form
     */
    function room_add() {
        $room = (object) array (
            'rid' => '',
            'type' => 'room',
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate('room', $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit('room', $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        return entity_get_controller('room')->save($room);
    }
    
    
    function room_info() {
        return t('Welcome to the administration page for your rooms!');
    }
    
    function room_page_title($room){
        return $room->room_number;
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        $return['room']['room'] = array(
            'form' => array(
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 1,
                ),
            ),
        );
    
        return $return;
    }
    
    
    function room_uri( $room ){
        return array(
            'path' => 'room/' . $room->rid,
        );
    }
    
    class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * Implements hook_load().
     */
    function entity_room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

     

 

添付 サイズ
entity_room.zip (2.55 KB) 2.55 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

エンティティ(Entity)に一つ以上のバンドル(Bundle)の定義ができます(カスタムモジュールentity_room.zip)

  • エンティティ(Enityt)の定義(hook_entity_info)にバンドル(bundle)定義があります('bundle'=>array())
    • バンドル定義に空の配列(bundle =>array())として定義する場合エンティティ(Entity)名と同じバンドルが自動的に定義されます
  • 一つエンティティに複数のバンドル定義ができます(カスタムモジュールentity_room.zip をダウンロード)
    • 例: roomエンティティに、シングルタイプルーム(single room)とツインタイプルーム(twin room)のバンドル(bundle)があります
      DrupalのEntityに複数のバンドル(Bundle)定義
    • 複数のバンドル定義するエンティティは以下のようです
      /**
       * Implements hook_entity_info().
       */
      function entity_room_entity_info()
      {
          $room_info['room'] = array(
              'label' => t('Room'),
              'entity class' => 'Entity',
              'controller class' => 'DrupalDefaultEntityController',
              'base table' => 'room',
              'fieldable' => TRUE,
              'entity keys' => array(
                  'id' => 'rid',
                  'label' => 'room_number',
                  'bundle' => 'room_type',     // DB上にroom_typeフィールドでバンドルを区別
              ),
              'bundles' => array(
                  'single_room'=> array(
                      'label' => 'Single Room',
                      'admin' => array(
                          'path' => 'admin/structure/single-room/manage',
                      ),
                  ),
                  'twin_room'=> array(
                      'label' => 'Twin Room',
                      'admin' => array(
                          'path' => 'admin/structure/twin-room/manage',
                      ),
                  ),
              ),
              'access callback' => 'access_room',
              'module' => 'entity_room',
          );
      
          return $room_info;
      }
      

バンドルのフィールド管理パス、権限の設定が必要です

  • 各バンドル(Bundle)にそれぞれの拡張フィールド管理ができます
  • そのため、各バンドルの拡張フィールドの管理画面を分ける必要があります
    • single room: 'path' => 'admin/structure/single-room/manage',
    • twin room: 'path' => 'admin/structure/twin-room/manage',
  • 各バンドルに対してエンティティでアクセス権限一括設定ができます
    • 'access callback' => 'access_room',

バンドルオブジェクトを区別するためentity_keysにbundleパラメーターの設定が必要

  • 一エンティティ(Entity)ごとに、DB上では一テーブルとなります
    • 上記例はroomテーブル(entity_room.installを参考)
  • 複数のバンドルを定義するので、当然どのようにバンドルを区別するか、そのキーが必要となります
    • 上記例は、バンドルを区別するroom_typeフィールドを追加しました
  • DB上のバンドル識別フィールドをentity_keysに設定する必要があります
    • 上記では、'bundle' => 'room_type',
  • このキーを設定しないと、実際にバンドルオブジェクトの取得はできないです

hook_field_extra_fields(). を実装して、バンドルの拡張フィールド にエンティティのプロパティ項目を追加

  • バンドルの拡張フィールド管理画面に、エンティティのプロパティがありません(継承関係でバンドルが下位になっています)
  • プロパティをフィールドように見せるために hook_field_extra_fields(). を実装します(実際にフィールド管理画面でプロパティの編集はできない)
    /**
     * Implements hook_field_extra_fields().
     * Field管理にRoomのプロパティ項目を追加(編集不可)
     */
    function entity_room_field_extra_fields()
    {
        $return = array();
        // For Single Room Bundle
        $return['room']['single_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
        // For Twin Room Bundle
        $return['room']['twin_room'] = array(
            'form' => array(
                'room_type' => array(
                    'label' => t('Room Type'),
                    'description' => t('The type of the room'),
                    'weight' => 1,
                ),
                'room_number' => array(
                    'label' => t('Room Number'),
                    'description' => t('The number of the room'),
                    'weight' => 2,
                ),
            ),
        );
    
        return $return;
    }
    

エンティティの取得、作成などの操作にhook_menu()を実装して行います

  • エンティティの取得、作成などはhook_menu()を実装します
  • エンティティ作成、表示にはFormAPIなどを実装しています
    /**
     * Implements hook_menu().
     */
    function entity_room_menu()
    {
        // シングル ルーム 管理画面
        $items['admin/structure/single-room/manage'] = array(
            'title' => t('Single Room Admin'),
            'description' => 'Manage Single Room structure',
            'page callback' => 'room_info',
            'page arguments' => array('Single Room') ,
            'access arguments' => array('administer rooms'),
        );
        $items['single-room/add'] = array(
            'title' => t('Add Single Room'),
            'page callback' => 'room_add',
            'page arguments' => array('single_room'),
            'access arguments' => array('create room'),
        );
    
        // ツインルーム管理が画面
        $items['admin/structure/twin-room/manage'] = array(
            'title' => 'Twin Room Admin',
            'description' => 'Manage Twin Room structure',
            'page callback' => 'room_info' ,
            'page arguments' => array('Twin Room'),
            'access arguments' => array('administer rooms'),
        );
        $items['twin-room/add'] = array(
            'title' => t('Add Twin Room'),
            'page callback' => 'room_add',
            'page arguments' => array('twin_room'),
            'access arguments' => array('create room'),
        );
    
        // Roomの表示
        $items['room/%room'] = array(
            'title callback' => 'room_page_title',
            'title arguments' => array(1),
            'page callback' => 'room_page_view',
            'page arguments' => array(1),
            'access arguments' => array('view rooms'),
            'type' => MENU_CALLBACK,
        );
    
        return $items;
    }
    
    /**
     * Implements hook_permission().
     */
    function entity_room_permission()
    {
        return array(
            'administer rooms' =>  array(
                'title' => t('Administer rooms'),
                'restrict access' => TRUE,
            ),
            'create room' =>  array(
                'title' => t('Create room'),
            ),
            'view rooms' => array(
                'title' => t('View Rooms'),
            )
        );
    }
    
    /**
     * 全員にRoomエンティティの無条件アクセス権限
     */
    function access_room(){
        return true ;
    }
    
    /**
     * create "add room" form
     */
    function room_add($type) {
        $room = (object) array (
            'rid' => '',
            'room_type' => $type,
            'room_number' => '',
        );
    
        return drupal_get_form('room_add_form', $room);
    }
    function room_add_form($form, &$form_state, $room) {
        $form['room_type'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Type'),
            '#default_value' => $room->room_type,
            '#disabled' => true,
            '#required' => TRUE,
        );
    
        $form['room_number'] = array(
            '#type' => 'textfield',
            '#title' => t('Room Number'),
            '#required' => TRUE,
        );
    
        field_attach_form('room', $room, $form, $form_state);
    
        $form['submit'] = array(
            '#type' => 'submit',
            '#value' => t('Save'),
            '#weight' => 10,
        );
    
    
        return $form;
    }
    
    function room_add_form_validate($form, &$form_state) {
        $room_submisttion = (object) $form_state['values'];
        field_attach_form_validate($form_state['values']['room_type'], $room_submisttion, $form, $form_state);
    }
    
    function room_add_form_submit($form, &$form_state) {
        $room_submission = (object) $form_state['values'];
        field_attach_submit($form_state['values']['room_type'], $room_submission, $form, $form_state);
        $room = room_save($room_submission);
        $form_state['redirect'] = "room/$room->rid";
    }
    
    function room_save(&$room) {
        drupal_write_record('room', $room);
        field_attach_insert('room', $room);
        return $room;
    }
    
    
    function room_info($type) {
        return t('Welcome to the administration page for your '.$type.'!');
    }
    
    function room_page_title($room){
        return $room->room_number."(".$room->room_type.")";
    }
    
    function room_page_view($room, $view_mode = 'full'){
    
        $room->content = array();
    
        // Build fields content.
        field_attach_prepare_view('room', array($room->rid => $room), $view_mode);
        entity_prepare_view('room', array($room->rid => $room));
        $room->content += field_attach_view('room', $room, $view_mode);
    
        return $room->content;
    }
    
    function room_uri( $room ){
        return array(
            'path' => 'room/'.$room->rid ,
        );
    }
    
    class RoomController extends EntityAPIController{
    //class RoomController extends DrupalDefaultEntityController{
        public function __construct($entityType) {
            parent::__construct($entityType);
        }
    
        // Entityオブジェクト保存
        public function save($room) {
            drupal_write_record('room', $room);
            field_attach_insert('room', $room);
            return $room;
        }
    
    }
    
    /**
     * hook_menuのURL引数のオブジェクト取得
     */
    function room_load($rid = NULL, $reset = FALSE){
    
        $rids = (isset ($rid) ? array($rid) : array());
        $room = room_load_multiple($rids, $reset);
        return $room ? reset ($room) : FALSE;
    }
    
    function room_load_multiple($rids = array(), $conditions = array(), $reset = FALSE){
        return entity_load('room', $rids, $conditions, $reset);
    }
    

 

添付 サイズ
entity_room.zip (2.84 KB) 2.84 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

一つのエンティティタイプ(Entity Type)に最低一つのバンドルが必要

  • Entityオブジェクトを生成する場合、最初エンティティタイプ(Entity Type)が必要
    • 例: 記事(Article)、基本ページ(Basic Page)を作成する前に、コンテントタイプが必要です(コンテントタイプ⇒エンティティタイプです、記事/基本ページはバンドルです)
  • 前回紹介した「DrupalのEntityを定義する簡単な例-4:複数のバンドルの作成/拡張フィールド追加 」例では一つのエンティティタイプに複数のバンドルを定義します
    • プログラミングでバンドル(例:シングルタイプ、ツインタイプのルーム)を定義します

問題点:プログラミングで定義したバンドルは任意に追加することはできません

  • 上記の例では、エンティティタイプを定義する同時にバンドルも定義します
  • 実際には、エンティティタイプが定義してから、必要に応じていろいろなバンドルを追加する必要があります
    • 例:ルームでは施設によって、ツインタイプのものがあれば、ないところもあります
    • 例:コンテントタイプに記事、基本ページ以外に、必要に応じていろいろなバンドル(例:予約など)追加ができます

解決:エンティティ(Entity)を利用して別のエンティティタイプのバンドルに定義します

  • モジュール:EntityAPIがこの方法を提供してくれました
  • 一つのエンティティ(例:room type)を別のエンティティタイプ(例:room)のバンドルにする定義ができます
    DrupalのEntityオブジェクトを他のエンティティタイプ(EntityType)のバンドルにする
  • 大きな利点は、エンティティタイプがプログラミングで定義、バンドルはDrupalのUIで登録することができます

一つのエンティティを他のエンティティのバンドルにする定義: "bundle of" にあります

  • プログラミングでエンティティを定義するときに、hook_entity_info を実装して定義します(前回も紹介したので、ここは詳細を省略)
  • 他のエンティティタイプのバンドルにする定義: "bundle of" => "room"  (room typeがroomのバンドルに指定)
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • カスタムモジュール(entity_room.zip)をダウンロードしてください
  • エンティティの具体な操作は次回で説明します
添付 サイズ
entity_room.zip (5.08 KB) 5.08 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
video
entity type

やりたいこと:Entityのプロパティをフィールドのように表示管理を行いたいです

  • 前回紹介した:「DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義 」例があります
    • Entityの表示は「entity_view()」関数を使用しました
      function room_view($room, $view_mode="full") {
      
          drupal_set_title(entity_label('room', $room));
      
          return entity_view('room', array(entity_id('room', $room) => $room), $view_mode);
      }
    • Roomエンティティのプロパティ(RoomNam、RoomArea←今回追加した)のRoom表示画面に表示できません
      エンティティの表示画面にエンティティプロパティが表示されていない
    • なぜRoomNameが表示されたか: hook_entity_info() の「entity keys」の「label」に定義されて、エンティティのタイトルとして表示させた
    • もちろん、FormAPIを利用して、RoomName/RoomAreaの表示ができます。ここで、Entity CRUD(EntityAPIに提供され)機能を利用してエンティティを表示させます

エンティティプロパティ(Entity Properties)を表示させるためEntityDefaultExtraFieldsControllerの実装が必要です

  • 今回「EntityDefaultExtraFieldsController」の実装例サンプル:entity_room.zip をダウンロードしてください
  • hook_entity_info定義に「'extra fields controller class' => 'EntityDefaultExtraFieldsController',」入れます
    /**
     * Implements hook_entity_info().
     */
    function entity_room_entity_info()
    {
        $return = array(
            'room' => array(
                'label' => t('Room'),
                'entity class' => 'RoomEntity',
                'label callback' => 'entity_class_label', // see RoomEntity class
                'uri callback' => 'entity_class_uri',     // see RoomEntity class
                'controller class' => 'RoomController',
                'base table' => 'room',
                'fieldable' => TRUE,
                'entity keys' => array(
                    'id' => 'rid',
                    'bundle' => 'room_type_sys',
                ),
                'bundle keys' => array(
                    'bundle' => 'room_type_sys',
                ),
                'bundles' => array(),
                'load hook' => 'room_load',
                'view modes' => array(
                    'full' => array(
                        'label' => t('Default'),
                        'custom settings' => FALSE,
                    ),
                ),
                'module' => 'entity_room',
                'access callback' => 'entity_room_access',
                'extra fields controller class' => 'EntityDefaultExtraFieldsController',
                'metadata controller class' => 'RoomEntityMetadataController',
            ),
        );
        $return['room_type'] = array(
            'label' => t('Room Type'),
            'entity class' => 'RoomTypeEntity',
            'controller class' => 'RoomTypeController',
            'base table' => 'room_type',
            'fieldable' => FALSE,
            'bundle of' => 'room',
            'exportable' => TRUE,
            'entity keys' => array(
                'id' => 'rtid',
                'name' => 'room_type_sys',
                'label' => 'room_type_label',
            ),
            'module' => 'entity_room',
            'admin ui' => array(                // Enable the entity API's admin UI.
                'path' => 'admin/structure/room-types',
                'file' => 'room_type.admin.inc',
                'controller class' => 'RoomTypeUIController',
            ),
            'access callback' => 'entity_room_access',
        );
    
        return $return;
    }
    
  • エンティティプロパティの情報を定義するため、hook_entity_infoに「'metadata controller class' => 'RoomEntityMetadataController', 」入れます
    class RoomEntityMetadataController extends EntityDefaultMetadataController {
        public function entityPropertyInfo()
        {
            $info = parent::entityPropertyInfo();
            $info[$this->type]['properties']['rid']=array(
                'label' => t('Room ID'),
                'type' => 'integer',
                'description' => t('Room Entity ID'),
                'schema field' => 'rid',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_type_sys']=array(
                'label' => t('Room Type Name'),
                'type' => 'text',
                'description' => t('Room Type Machine Name'),
                'schema field' => 'room_type_sys',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_label']=array(
                'label' => t('Room Name'),
                'type' => 'text',
                'description' => t('Room Name'),
                'schema field' => 'room_label',
                'setter callback' => 'entity_property_verbatim_set',
            );
            $info[$this->type]['properties']['room_area']=array(
                'label' => t('Room Area'),
                'type' => 'text',
                'description' => t('Room Area Name'),
                'schema field' => 'room_area',
                'setter callback' => 'entity_property_verbatim_set',
            );
            return $info;
    
        }
    }
    
  • hook_entity_infoに「'metadata controller class'  」を利用せず、「 hook_entity_property_info() 」を実装してもできます

エンティティ管理画面の「フィールド管理」/「表示管理」にエンティティのプロパティが表示される

  • 「表示管理」でプロパティの表示/非表示設定ができます
    エンティティのプロパティの表示/日表示設定
  • エンティティ表示画面にエンティティのプロパティが表示されるようになります
     

 

添付 サイズ
entity_room.zip (6.47 KB) 6.47 KB
Embedded thumbnail for DrupalのEntityを定義する簡単な例-7:EntityDefaultExtraFieldsControllerを実装してエンティティのプロパティを表示させます
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
drupal
entity type

D7ではエンティティ(Entity)に対応していないサードパーティーのモジュールが数多く存在しています

  • Drupal7現時点でも、エンティティタイプ(EntityType)に対応しているモジュールが数多く存在しています
  • エンティティをサポートするサブモジュール/パッチが登場したモジュールが多いです(特にメジャーなモジュール)
  • D7でエンティティを導入する場合、各モジュールがエンティティとの対応チェックは必要でしょう
    • エンティティが導入後に、一部分でエンティティを対応しなければ、サイトの機能に影響を与えかねないです

エンティティ()に対応するサブモジュール/パッチをネットでチェックします

  • 前回エンティティの定義:DrupalのEntityを定義する簡単な例-6:EntityAPI(EntityAPIControllerExportable)でバンドルの管理画面の定義
    • この例のRoomエンティティを例にします
  • よく使用されているモジュール(例:xml sitemap, pathautoなど)もエンティティタイプを対応していないです
  • モジュール(xml sitemap)の場合エンティティ対応のパッチが出ています
    • パッチ当て後に、xml sitemapの管理画面に定義したエンティティタイプが現れます
      モジュール(xml sitemap)のエンティティタイプ対応パッチ
  • モジュール(pathauto)ではエンティティ対応するサブモジュール(Pathauto Entity)があります
    • モジュールをインストールすれば、URLエリアスの管理画面に「エンティティ」タブが現れ、必要なエンティティタイプを選択することができます
      モジュール(pathauto entity)よりエンティティタイプの選択
Embedded thumbnail for Drupalのモジュール(EntityAPI)に対応していないサードパーティーのモジュールが多く存在しています
drupal
entity type

モジュール(EntityAPI)がDrupalコアにある「entity」を拡張したものです

  • モジュール(EntityAPI)はAPIモジュールであり、エンドモジュールではありません(インストール後に画面には何の変化もありません)。Drupalへのカスタマイズ、開発するためにAPIです。
    • EntityAPIを利用する場合、実装したhook_entity_info() のパラメーター: "controller class" => "EntityAPIControllerExportable"、"controller class" => "EntityAPIController" を定義します
  • プログラミングでEntityを定義する例(DrupalのEntityを定義する簡単な例-3:バンドルの作成/拡張フィールド追加)では、コアのEntity(DrupalDefaultEntityController)を使用した例です

EntityAPI(EntityAPIControllerExportable)を実装してバンドルの管理画面を定義します

  • EntityAPI実装よりEntity自身をほかのntityのバンドル(Bundle)にすることことができます
    • 例: DrupalのEntityを定義する簡単な例-5:エンティティ(Entity)を利用して別のエンティティタイプ(Entity Type)のバンドルに作成
  • hook_entity_info() のバンドルを管理するUIの定義パラメーター: ”admin ui” => array()
    • "exportable" => TRUE : エンティティ定義のエクスポートができるかの定義
    • "fieldable" => TRUE :  フィールドの拡張可能かの定義(バンドル(room type)内で定義ではなく、エンティティタイプ内で定義:上記例ではroomエンティティで定義)
      DrupalのEntityAPIでバンドル管理画面を定義

hook_entity_info_alter()を実装してエンティティの拡張フィールド管理をできるように

  • バンドル管理画面(RoomType管理)でバンドルを作成します
  • 各バンドル関連のエンティティに拡張フィールドの追加、表示変更ができます
  • これらの操作をできるように、hook_entity_info_alter()の実装が必要です
    /**
     * 追加されたバンドル(RoomType)に拡張フィールド操作URIの追加
     * Implements hook_entity_info_alter().
     */
    function entity_room_entity_info_alter(&$entity_info)
    {
        foreach (room_types() as $type => $info) {
            $entity_info['room']['bundles'][$type] = array(
                'label' => $info->room_type_label,
                'admin' => array(
                    'path' => 'admin/structure/room-types/manage/%room_type',
                    'real path' => 'admin/structure/room-types/manage/' . $type,
                    'bundle argument' => 4,
                ),
            );
        }
    }
    
    // room_type_sys でデータの取得
    // room_type入力がなければ、全部のRoomTypeを返す
    function room_type_load($room_type=null){
        return room_types( $room_type ) ;
    }
    
    function room_types( $room_type = null ){
        $types = entity_load_multiple_by_name( 'room_type', isset($room_type) ? array($room_type) : false ) ;
        return isset( $room_type ) ? reset($types) : $types ;
    }
    
    • なぜhook_entity_info_alter()の実装が必要か?バンドル(room_type)が作成する前にエンティティの実体がないからです(上記例では必要に応じでバンドル作成)
    • 後ろにある「function room_type_load()」はパスにあるワイドカード( 'path' => 'admin/structure/room-types/manage/%room_type')に使用されます
  • hook_entity_info_alter()を実装しない、または間違って実装(例:pathのワイドカード使用不正)すると拡張フィールド管理ページが見つからないエラーになります
    hook_entity_info_alterを実装しない、または間違って実装すると拡張フィールド管理画面が見つからないエラー

エンティティをバンドルにするデータ構成:エンティティタイプの識別キーが必要

  • 上記例のエンティティタイプ、バンドルの関係は以下のようです
    • エンティティタイプ(entity type) : room
    • バンドル(bundle) : シングル(single_type)、 ツイン(twin_type) など(必要に応じて作成)
  • 作成したエンティティ本体(room)がバンドル(single_type, twin_type)どの関連があるので、二つのテーブル間の参照キーが必要となります
    • 例: 1001室 ⇒ シングル(single_type)、2001室(twin_type)
    • roomテーブルにある「room_type_sys」フィールドにバンドルであるroom_typeにある「room_type_sys」フィールドが参照キーとなります
      EntityTypeとBundleの間に参照キーが必要
添付 サイズ
custom_table_2.zip (1.67 KB) 1.67 KB
ホーム

古松

検索

Article Category

  • apache(7)
  • css(19)
  • drupal(295)
  • Electron(4)
  • html(34)
  • javascript(27)
  • laravel(4)
  • linux(5)
  • macOS(2)
  • mysql(13)
  • php(19)
  • python(4)
  • SEO(12)
  • video(72)
  • Visual Studio Code(4)
  • windows(13)
  • wordpress(32)